package com.test.simplechat.server;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.FixedRecvByteBufAllocator;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * netty聊天服务器
 *
 * @author wen
 */
public class NettyChatServer {
    private final static Logger LOGGER = LoggerFactory.getLogger(NettyChatServer.class);

    private  int port;
    private String wsPath;


    public NettyChatServer(int port, String wsPath) {
        this.port = port;
        this.wsPath = wsPath;
    }

    //开启服务
    public void start() throws Exception {
        MyChannelHandlerPool.CHANNEL_ID_MAP.clear();
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024) //配置TCP参数，握手字符串长度设置
                    .handler(new LoggingHandler(LogLevel.DEBUG))
                    .childOption(ChannelOption.TCP_NODELAY, true)//TCP_NODELAY算法，尽可能发送大块数据，减少充斥的小块数据
                    .childOption(ChannelOption.SO_KEEPALIVE, true)//开启心跳包活机制，就是客户端、服务端建立连接处于ESTABLISHED状态，超过2小时没有交流，机制会被启动
                    .childOption(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(592048))//配置固定长度接收缓存区分配器
                    .group(bossGroup, group)//boss辅助客户端的tcp连接请求  worker负责与客户端之前的读写操作
                    .channel(NioServerSocketChannel.class) //配置客户端的channel类型
                    .childHandler(new MyChannelHandler(wsPath));
            ChannelFuture cf = serverBootstrap.bind(port).sync(); // 服务器异步创建绑定
            LOGGER.debug("NettyChatServer启动,正在监听：{},config:{} ", cf.channel().localAddress(), cf.channel().config().getOptions());
            cf.channel().closeFuture().sync(); // 关闭服务器通道
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully().sync(); // 释放线程池资源
            bossGroup.shutdownGracefully().sync();

        }

    }
}

